package org.ihelpuoo.weboo.module;

import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.ihelpuoo.core.Nut;
import org.ihelpuoo.io.CharInputStream;
import org.ihelpuoo.lang.ObjectUtils;
import org.ihelpuoo.lang.SegmentNotFoundException;
import org.ihelpuoo.orm.IIIException;
import org.ihelpuoo.orm.POJO;
import org.ihelpuoo.orm.filter.FieldFilter;
import org.ihelpuoo.parser.segment.Segment;
import org.ihelpuoo.parser.segment.SegmentFactory;
import org.ihelpuoo.weboo.Weboo;
import org.ihelpuoo.weboo.action.http.Action;
import org.ihelpuoo.weboo.exception.ModuleNotFoundException;
import org.ihelpuoo.weboo.security.Session;
import org.ihelpuoo.weboo.security.SessionImpl;
import org.ihelpuoo.weboo.util.ForwardTarget;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

public abstract class AbstractContext
{

	protected AbstractContext(ModuleContext mc, HttpServletRequest request,
			HttpServletResponse response)
	{
		this.mc = mc;
		this.request = request;
		this.response = response;
	}

	protected ModuleContext			mc;
	protected HttpServletRequest	request;
	protected HttpServletResponse	response;
	protected HttpParams			_params;

	public SegmentFactory segments()
	{
		return this.getWebooConfig().segments();
	}

	public ModuleContext getModuleContext()
	{
		return mc;
	}

	public ModuleManager moduleSet()
	{
		return mc.getModuleManager();
	}

	public Nut nut()
	{
		return mc.nut();
	}

	public String getModuleName()
	{
		return mc.getModuleName();
	}

	public String getContextPath()
	{
		return request.getContextPath();
	}

	public HttpServletRequest getRequest()
	{
		return request;
	}

	public HttpServletResponse getResponse()
	{
		return response;
	}

	public Session getSession()
	{
		return SessionImpl.wrap(request);
	}

	public Object getFormObject(Object obj) throws IIIException
	{
		return getFormObject(obj,null,null);
	}

	public Object getFormObject(Class type) throws IIIException
	{
		return getFormObject(type,null,null);
	}

	public Object getFormObject(Object obj, FieldFilter actived, FieldFilter locked)
			throws IIIException
	{
		return pojo().fetch(request,obj,actived,locked);
	}

	public Object getFormObject(Class type, FieldFilter actived, FieldFilter locked)
			throws IIIException
	{
		Object obj = ObjectUtils.newInstance(type);
		if (null == obj)
			return null;
		return pojo().fetch(request,obj,actived,locked);
	}

	public POJO pojo()
	{
		return mc.getWebooConfig().pojo();
	}

	public Locale getSessionLocale()
	{
		return SessionImpl.wrap(request).getLocale();
	}

	public Locale getAvaiableLocale(String name)
	{
		return mc.getModuleManager().getLocale(name);
	}

	public List<Locale> getAvaiableLocales()
	{
		return mc.getModuleManager().getLocales();
	}

	public HttpParams params()
	{
		if (this._params == null)
			this._params = new HttpParams(request);
		return this._params;
	}

	public String getMessage(String key)
	{
		return mc.getMessage(getSessionLocale(),key);
	}

	public Module getModule(String name) throws ModuleNotFoundException
	{
		return mc.getModuleManager().getModule(name);
	}

	public Module getDefaultModule()
	{
		return mc.getModuleManager().getDefaultModule();
	}

	public WebooConfig getWebooConfig()
	{
		return WebooConfig.me(request);
	}

	public Document newDocument()
	{
		return this.getWebooConfig().dom().newDocument();
	}

	public Document parseDocument(CharSequence cs) throws SAXException
	{
		try
		{
			return getWebooConfig().dom().parse(new CharInputStream(cs));
		}
		catch (IOException e)
		{
			throw new RuntimeException(e);
		}
	}

	public Document parseDocument(InputStream ins) throws SAXException
	{
		try
		{
			return getWebooConfig().dom().parse(ins);
		}
		catch (IOException e)
		{
			throw new RuntimeException(e);
		}
	}

	public Segment createPattern(String name) throws SegmentNotFoundException
	{
		return getModuleContext().patterns(request)
				.create(getWebooConfig().formatPatternName(name));
	}

	public Segment createPattern(String name, String module) throws SegmentNotFoundException,
			ModuleNotFoundException
	{
		return this.getModule(module).getModuleContext().patterns(request).create(
				getWebooConfig().formatPatternName(name));
	}

	public void forward(String fwd, boolean redirect) throws Exception
	{
		if (null == fwd)
			return;
		ForwardTarget tar = new ForwardTarget(fwd);
		if (redirect)
		{
			StringBuffer sb = new StringBuffer(getContextPath()).append(tar.isForAction() ? tar
					.getActionPath(getWebooConfig().getActionSuffix()) : tar.getPath());
			response.sendRedirect(sb.toString());
		}
		else
		{
			if (tar.isForAction())
			{
				Module module = this.getModule(tar.getModuleName());
				ModuleContext mc = module.getModuleContext();
				Action action = mc.actions().getAction(tar.getActionName());
				ActionConfig ac = mc.actions().getActionConfig(tar.getActionName());
				action.execute(new ActionContext(mc,ac,request,response));
			}
			else
			{
				RequestDispatcher rd = getSession().getServletContext().getRequestDispatcher(
						tar.getPath());
				rd.forward(request,response);
			}
		}
	}

	public String getForwardName()
	{
		Object obj = request.getAttribute(Weboo.FORWARD_NAME);
		if (null == obj)
			return null;
		return obj.toString();
	}

	public void setForwardName(String name)
	{
		request.setAttribute(Weboo.FORWARD_NAME,name);
	}

	public Calendar now()
	{
		return Calendar.getInstance(getRequest().getLocale());
	}

	public Calendar now(Locale locale)
	{
		return Calendar.getInstance(locale);
	}
}
